package cn.sciento.farm.devicemanager.gateway.uplink.service.lorawan;


import cn.sciento.farm.devicemanager.common.constant.MqttConstant;
import cn.sciento.farm.devicemanager.gateway.model.uplink.DeviceStatus;
import cn.sciento.farm.devicemanager.gateway.model.uplink.LorawanHeart;
import cn.sciento.farm.devicemanager.gateway.uplink.service.sensor.MessageAllDisposeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author wumu
 */
@Slf4j
@Service
public class LorawanHeartListener {

    private ScheduledExecutorService scheduledExecutor;

    private final int INTERNAL_TIME  = 30*60;

    private ConcurrentMap<String, LorawanHeart> concurrentMap = new ConcurrentHashMap<String, LorawanHeart>();

    @Autowired
    private MessageAllDisposeService messageAllDisposeService;

    public LorawanHeartListener() {
        this.scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    }

    @PostConstruct
    public void start(){
        scheduledExecutor.scheduleAtFixedRate(new TimeoutHandler(),INTERNAL_TIME,INTERNAL_TIME,TimeUnit.SECONDS);
    }

    public LorawanHeart saveHeart(String devEUI){
        LorawanHeart lorawanHeart = new LorawanHeart();
        lorawanHeart.setLastTime(System.currentTimeMillis());
        if(!concurrentMap.containsKey(devEUI)){
//            log.info("这里不包含lorawan: "+devEUI);
            sendOnline(devEUI);
        }
        return concurrentMap.put(devEUI,lorawanHeart);
    }

    public void delete(String eui){
        concurrentMap.remove(eui);
    }


    private void sendOnline(String devEUI){
        scheduledExecutor.execute(new Runnable() {
            @Override
            public void run() {
                DeviceStatus deviceStatus = DeviceStatus.builder()
                        .eui(devEUI)
                        .status(MqttConstant.DEVICE_ONLINE_CODE)
                        .build();
                messageAllDisposeService.changeOnline(deviceStatus);
            }
        });
    }




    class TimeoutHandler implements Runnable{

        @Override
        public void run() {
            long currentTime = System.currentTimeMillis();
            Iterator<Map.Entry<String,LorawanHeart>> iterator = concurrentMap.entrySet().iterator();
            while (iterator.hasNext()){
                Map.Entry<String,LorawanHeart> entry = iterator.next();
                String devEUI = entry.getKey();
                LorawanHeart lorawanHeart = entry.getValue();
                if(lorawanHeart.getLastTime() < currentTime - lorawanHeart.getKeepAlive()*1000L){
                    // 发送离线包
                            log.info("处理离线lorawan :"+devEUI);
                    messageAllDisposeService.changeOnline(DeviceStatus.builder()
                            .eui(devEUI)
                            .status(MqttConstant.DEVICE_OFFLINE_CODE)
                            .build());
                    // 移除
                    iterator.remove();
                }
            }

        }
    }
}
